package com.lesserpand.rabbitmq.threadpool.thread;

import org.springframework.stereotype.Component;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author pand
 * @version 0.0.1
 * @package com.topinfo.locationservice.utils.thread
 * @description 线程池执行器
 * @date Created in 2019/4/1 15:00
 * @company
 * @copyright Copyright (c) 2017
 * @modified By
 */
@Component
public class SyncExecutor {

    /**
     * 核心线程数，默认情况下核心线程会一直存活
     */
    private static final Integer CORE_POOL_SIZE = 8;

    /**
     * 线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。
     */
    private static final Integer MAX_IMUM_POOLSIZE = 20;

    /**
     * 非核心线程的闲置超时时间，超过这个时间就会被回收.1分钟
     */
    private static final Integer KEEP_ALIVE_TIME = 60;

    /**
     * 任务缓存队列，用来保存等待中的任务，等待worker线程空闲时执行任务
     */
    private LinkedBlockingQueue LINKED_BLOCKING_QUEUE = new LinkedBlockingQueue();

    /**
     * 线程工厂，提供创建新线程的功能
     */
    private SyncThreadFactory THREAD_FACTORY = new SyncThreadFactory();

    /**
     * 当线程池中的资源已经全部使用，添加新线程被拒绝时，会调用RejectedExecutionHandler的rejectedExecution方法
     */
    private SyncRejectedExecutionHandler HANDLER = new SyncRejectedExecutionHandler();

    private ThreadPoolExecutor executorService;

    private SyncExecutor() {
        executorService =
                new ThreadPoolExecutor(
                        CORE_POOL_SIZE, // 核心线程数，默认情况下核心线程会一直存活
                        MAX_IMUM_POOLSIZE, // 线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。
                        KEEP_ALIVE_TIME, // 非核心线程的闲置超时时间，超过这个时间就会被回收.1分钟
                        TimeUnit.SECONDS, //
                        LINKED_BLOCKING_QUEUE, // 任务缓存队列，用来保存等待中的任务，等待worker线程空闲时执行任务
                        THREAD_FACTORY, // 线程工厂，提供创建新线程的功能
                        HANDLER // 当线程池中的资源已经全部使用，添加新线程被拒绝时，会调用RejectedExecutionHandler的rejectedExecution方法
                );
    }

    public ThreadPoolExecutor getExecutorService() {
        return executorService;
    }

    /**
     * 定时任务启动多个线程获取定位数据
     *
     * @param runnable
     */
    public void startUpThread(Runnable runnable) {
        executorService.execute(runnable);
    }

}